using System;
using System.Collections.Generic;
using System.Text;
using CLELCore.Executable;
using CLELCore.Assembly.StreamTables;
using CLELCore.Assembly.StreamTables.StreamTableRows;
using CLELCore.Assembly.BlobStreams;
using CLELCore.Assembly.Debug;
using CLELCore.Assembly.Debug.DebugInformation;
using CLELCore.Assembly.CLELInstructions;
using CLELCore.Assembly.MethodHeaderDataSections;
using CLELCore.Assembly.MethodHeaderDataSections.MethodHeaderDataSectionRows;
using CLELCore.Assembly.BlobStreams.BlobInfo;
using CLELCore.Assembly.Descriptors.ClassDescriptors;

namespace CLELCore.Assembly.Parser.ValidAssemblyParser
{
	public class CLELValidAssemblyTextParser
	{
		private CLELAssembly _asm;
		private byte[] _buffer;
		private bool _little_endian;
		private CLELLogger _log;
		private int _rva;
		private AssemblyTextSection _text;
		private int _blob_size;
		private int _strings_size;
		private int _guid_size;

		public CLELValidAssemblyTextParser(CLELAssembly asm,byte[] buffer,
			bool little_endian,CLELLogger log,int rva)
		{
			_asm = asm;
			_buffer = buffer;
			_little_endian = little_endian;
			_log = log;
			_rva = rva;
		}

		public AssemblyTextSection ParseTextSection()
		{
			_text = new AssemblyTextSection();
			
			ParseEntryPoint();
			ParseCLIHeader();
			ParseStrongNameSignature();
			ParseImportTable();
			ParseImportAddressTable();
			ParseImportLookupTable();
			ParseNameTable();
			int next_rva = ParseMetadataRoot();
			ParseStreamHeaders(next_rva);
			ParseStringStream();
			ParseGUIDStream();
			ParseBlobStream();
			ParseUSStream();
			ParseTildaStream();
			ParseFieldDefaultValues();
			ParseMethodHeaders();
			ParseCLIResources();
			ParseDebug();

			return _text;
		}

		private int ParseMetadataRoot()
		{
			DataDirectory metadata_dd = _text.CLIHeader.Metadata;
			int metadata_offset = metadata_dd.VirtualAddress - _rva;
			int metadata_size = metadata_dd.Size;
			
			if(metadata_offset < 0 || metadata_offset+metadata_size >= _buffer.Length)
			{
				_log.WriteLine("Error metadata offset out of bounds: " + metadata_offset);
				throw new CLELParserException("Error metadata offset out of bounds: "+ metadata_offset);
			}

			MetadataRoot metadata = new MetadataRoot();

			int version_length;
			int after_version;
			if(_little_endian)
			{
				metadata.Signature = Endiness.IntLittleToBigEndian(_buffer[metadata_offset],_buffer[metadata_offset+1],_buffer[metadata_offset+2],_buffer[metadata_offset+3]);
				metadata.MajorVersion = Endiness.ShortLittleToBigEndian(_buffer[metadata_offset+4],_buffer[metadata_offset+5]);
				metadata.MinorVersion = Endiness.ShortLittleToBigEndian(_buffer[metadata_offset+6],_buffer[metadata_offset+7]);
				metadata.Reserved = Endiness.IntLittleToBigEndian(_buffer[metadata_offset+8],_buffer[metadata_offset+9],_buffer[metadata_offset+10],_buffer[metadata_offset+11]);
				version_length = Endiness.IntLittleToBigEndian(_buffer[metadata_offset+12],_buffer[metadata_offset+13],_buffer[metadata_offset+14],_buffer[metadata_offset+15]);
				metadata.VersionLength = version_length;
				after_version = version_length + metadata_offset+16;
				metadata.Flags = Endiness.ShortLittleToBigEndian(_buffer[after_version],_buffer[after_version+1]);
				metadata.Streams = Endiness.ShortLittleToBigEndian(_buffer[after_version+2],_buffer[after_version+3]);
			}
			else
			{
				metadata.Signature = Endiness.IntBigToLittleEndian(_buffer[metadata_offset],_buffer[metadata_offset+1],_buffer[metadata_offset+2],_buffer[metadata_offset+3]);
				metadata.MajorVersion = Endiness.ShortBigToLittleEndian(_buffer[metadata_offset+4],_buffer[metadata_offset+5]);
				metadata.MinorVersion = Endiness.ShortBigToLittleEndian(_buffer[metadata_offset+6],_buffer[metadata_offset+7]);
				metadata.Reserved = Endiness.IntBigToLittleEndian(_buffer[metadata_offset+8],_buffer[metadata_offset+9],_buffer[metadata_offset+10],_buffer[metadata_offset+11]);
				version_length = Endiness.IntBigToLittleEndian(_buffer[metadata_offset+12],_buffer[metadata_offset+13],_buffer[metadata_offset+14],_buffer[metadata_offset+15]);
				metadata.VersionLength = version_length;
				after_version = version_length + metadata_offset+16;
				metadata.Flags = Endiness.ShortBigToLittleEndian(_buffer[after_version],_buffer[after_version+1]);
				metadata.Streams = Endiness.ShortBigToLittleEndian(_buffer[after_version+2],_buffer[after_version+3]);
			}

			int i;
			byte[] version = new byte[version_length];
			int version_offset = metadata_offset+16;
			for(i = 0;i < version_length;i++)
				version[i] = _buffer[version_offset+i];
			metadata.Version = version;

			_text.MetadataRoot = metadata;
			return after_version+4;
		}

		private void ParseStreamHeaders(int next_rva)
		{
			int num_streams = _text.MetadataRoot.Streams;
			if(num_streams < 0)
			{
				_log.WriteLine("Error number of streams out of bounds: " + num_streams);
				throw new CLELParserException("Error number of streams out of bounds: "+ num_streams);
			}

			StreamHeaders headers = new StreamHeaders();
			StreamHeader sh;
			int i,j;
			int next = next_rva;
			byte [] name;
			byte temp;
			for(i = 0;i < num_streams;i++)
			{
				sh = new StreamHeader();
				if(_little_endian)
				{
					sh.Offset = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					sh.Size = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
				}
				else
				{
					sh.Offset = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					sh.Size = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
				}
				temp = _buffer[next+9];
				if(temp == 0x53) //#Strings
				{
					name = new byte[StreamHeader.STRINGS_NAME_SIZE];
				}
				else if(temp == 0x47) //#GUID
				{
					name = new byte[StreamHeader.GUID_NAME_SIZE];
				}
				else if( temp == 0x42) //#Blob
				{
					name = new byte[StreamHeader.BLOB_NAME_SIZE];
				}
				else if(temp == 0x7e) //#~
				{
					name = new byte[StreamHeader.TILDA_NAME_SIZE];
				}
				else if(temp == 0x55) //#US
				{
					name = new byte[StreamHeader.US_NAME_SIZE];
				}
				else
				{
					_log.WriteLine("Error unknown stream name: " + temp);
					throw new CLELParserException("Error unknown stream name: "+ temp);
				}
				next += 8;
				for(j = 0;j < name.Length;j++)
					name[j] = _buffer[next+j];
				sh.Name = name;
				next += name.Length;
				headers.Add(sh);
			}
			_text.StreamHeaders = headers;
		}

		private void ParseTildaStream()
		{
			DataDirectory metadata_dd = _text.CLIHeader.Metadata;
			int metadata_offset = metadata_dd.VirtualAddress;

			StreamHeader tilda_sh = _text.StreamHeaders.GetStreamHeader(StreamHeader.TILDA_NAME);
			if(tilda_sh == null)
				return;
			int tilda_offset = metadata_offset-_rva+tilda_sh.Offset;
			int tilda_size = tilda_sh.Size;
			if(tilda_offset < 0 || tilda_offset+tilda_size >= _buffer.Length)
			{
				_log.WriteLine("Error pound tilda stream out of bounds: " + tilda_offset);
				throw new CLELParserException("Error pound tilda stream out of bounds: "+ tilda_offset);
			}

			PoundTildaStream tilda = new PoundTildaStream();

			if(_little_endian)
			{
				tilda.Reserved = Endiness.IntLittleToBigEndian(_buffer[tilda_offset],_buffer[tilda_offset+1],_buffer[tilda_offset+2],_buffer[tilda_offset+3]);
				tilda.Valid = Endiness.LongLittleToBigEndian(_buffer[tilda_offset+8],_buffer[tilda_offset+9],_buffer[tilda_offset+10],_buffer[tilda_offset+11],_buffer[tilda_offset+12],_buffer[tilda_offset+13],_buffer[tilda_offset+14],_buffer[tilda_offset+15]);
				tilda.Sorted = Endiness.LongLittleToBigEndian(_buffer[tilda_offset+16],_buffer[tilda_offset+17],_buffer[tilda_offset+18],_buffer[tilda_offset+19],_buffer[tilda_offset+20],_buffer[tilda_offset+21],_buffer[tilda_offset+22],_buffer[tilda_offset+23]);
			}
			else
			{
				tilda.Reserved = Endiness.IntBigToLittleEndian(_buffer[tilda_offset],_buffer[tilda_offset+1],_buffer[tilda_offset+2],_buffer[tilda_offset+3]);
				tilda.Valid = Endiness.LongBigToLittleEndian(_buffer[tilda_offset+8],_buffer[tilda_offset+9],_buffer[tilda_offset+10],_buffer[tilda_offset+11],_buffer[tilda_offset+12],_buffer[tilda_offset+13],_buffer[tilda_offset+14],_buffer[tilda_offset+15]);
				tilda.Sorted = Endiness.LongBigToLittleEndian(_buffer[tilda_offset+16],_buffer[tilda_offset+17],_buffer[tilda_offset+18],_buffer[tilda_offset+19],_buffer[tilda_offset+20],_buffer[tilda_offset+21],_buffer[tilda_offset+22],_buffer[tilda_offset+23]);
			}

			tilda.MajorVersion = _buffer[tilda_offset+4];
			tilda.MinorVersion = _buffer[tilda_offset+5];
			tilda.HeapSizes = _buffer[tilda_offset+6];
			tilda.Reserved2 = _buffer[tilda_offset+7];
			
			int i;
			int [] num_rows = new int[64];
			long valid = tilda.Valid;
			int next = tilda_offset+24;
			
			for(i = 0;i < 64;i++)
			{
				if(Bits.IsBitSet(i,valid))
				{
					if(_little_endian)
						num_rows[i] = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					else
						num_rows[i] = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
				}
				else
					num_rows[i] = 0;
			}
			tilda.TableRows = num_rows;

			_blob_size = _text.BlobStream.Size;
			_strings_size = _text.StringsStream.Size;
			_guid_size = _text.GUIDStream.Size;

			StreamTable[] tables = new StreamTable[64];
			tilda.Tables = tables;

			_text.PoundTildaStream = tilda;
			for(i = 0;i < 64;i++)
			{
				if(num_rows[i] > 0)
				{
					tables[i] = ReadStreamTable(i,num_rows,ref next);
				}
			}
		}

		private StreamTable ReadStreamTable(int type,int [] num_rows,ref int offset)
		{
			StreamTable st = null;
			switch(type)
			{
				case StreamTable.ASSEMBLY_TABLE:
					st = ReadAssemblyTable(num_rows,ref offset);
					break;
				case StreamTable.ASSEMBLYOS_TABLE:
					st = ReadAssemblyOSTable(num_rows,ref offset);
					break;
				case StreamTable.ASSEMBLYPROCESSOR_TABLE:
					st = ReadAssemblyProcessorTable(num_rows,ref offset);
					break;
				case StreamTable.ASSEMBLYREF_TABLE:
					st = ReadAssemblyRefTable(num_rows,ref offset);
					break;
				case StreamTable.ASSEMBLYREFOS_TABLE:
					st = ReadAssemblyRefOSTable(num_rows,ref offset);
					break;
				case StreamTable.ASSEMBLYREFPROCESSOR_TABLE:
					st = ReadAssemblyRefProcessorTable(num_rows,ref offset);
					break;
				case StreamTable.CLASSLAYOUT_TABLE:
					st = ReadClassLayoutTable(num_rows,ref offset);
					break;
				case StreamTable.CONSTANT_TABLE:
					st = ReadConstantTable(num_rows,ref offset);
					break;
				case StreamTable.CUSTUMATTRIBUTE_TABLE:
					st = ReadCustomAttributeTable(num_rows,ref offset);
					break;
				case StreamTable.DECLSECURITY_TABLE:
					st = ReadDeclSecurityTable(num_rows,ref offset);
					break;
				case StreamTable.EVENT_TABLE:
					st = ReadEventTable(num_rows,ref offset);
					break;
				case StreamTable.EVENTMAP_TABLE:
					st = ReadEventMapTable(num_rows,ref offset);
					break;
				case StreamTable.EXPORTEDTYPE_TABLE:
					st = ReadExportedTypeTable(num_rows,ref offset);
					break;
				case StreamTable.FIELD_TABLE:
					st = ReadFieldTable(num_rows,ref offset);
					break;
				case StreamTable.FIELDLAYOUT_TABLE:
					st = ReadFieldLayoutTable(num_rows,ref offset);
					break;
				case StreamTable.FIELDMARSHAL_TABLE:
					st = ReadFieldMarshalTable(num_rows,ref offset);
					break;
				case StreamTable.FIELDRVA_TABLE:
					st = ReadFieldRVATable(num_rows,ref offset);
					break;
				case StreamTable.FILE_TABLE:
					st = ReadFileTable(num_rows,ref offset);
					break;
				case StreamTable.GENERICPARAM_TABLE:
					st = ReadGenericParamTable(num_rows,ref offset);
					break;
				case StreamTable.GENERICPARAMCONSTRAINT_TABLE:
					st = ReadGenericParamConstraintTable(num_rows,ref offset);
					break;
				case StreamTable.IMPLMAP_TABLE:
					st = ReadImplMapTable(num_rows,ref offset);
					break;
				case StreamTable.INTERFACEIMPL_TABLE:
					st = ReadInterfaceImplTable(num_rows,ref offset);
					break;
				case StreamTable.MANIFESTRESOURCE_TABLE:
					st = ReadManifestResourceTable(num_rows,ref offset);
					break;
				case StreamTable.MEMBERREF_TABLE:
					st = ReadMemberRefTable(num_rows,ref offset);
					break;
				case StreamTable.METHODDEF_TABLE:
					st = ReadMethodDefTable(num_rows,ref offset);
					break;
				case StreamTable.METHODIMPL_TABLE:
					st = ReadMethodImplTable(num_rows,ref offset);
					break;
				case StreamTable.METHODSEMANTICS_TABLE:
					st = ReadMethodSemanticsTable(num_rows,ref offset);
					break;
				case StreamTable.METHODSPEC_TABLE:
					st = ReadMethodSpecTable(num_rows,ref offset);
					break;
				case StreamTable.MODULE_TABLE:
					st = ReadModuleTable(num_rows,ref offset);
					break;
				case StreamTable.MODULEREF_TABLE:
					st = ReadModuleRefTable(num_rows,ref offset);
					break;
				case StreamTable.NESTEDCLASS_TABLE:
					st = ReadNestedClassTable(num_rows,ref offset);
					break;
				case StreamTable.PARAM_TABLE:
					st = ReadParamTable(num_rows,ref offset);
					break;
				case StreamTable.PROPERTY_TABLE:
					st = ReadPropertyTable(num_rows,ref offset);
					break;
				case StreamTable.PROPERTYMAP_TABLE:
					st = ReadPropertyMapTable(num_rows,ref offset);
					break;
				case StreamTable.STANDALONESIG_TABLE:
					st = ReadStandAloneSigTable(num_rows,ref offset);
					break;
				case StreamTable.TYPEDEF_TABLE:
					st = ReadTypeDefTable(num_rows,ref offset);
					break;
				case StreamTable.TYPEREF_TABLE:
					st = ReadTypeRefTable(num_rows,ref offset);
					break;
				case StreamTable.TYPESPEC_TABLE:
					st = ReadTypeSpecTable(num_rows,ref offset);
					break;
				default:
					_log.WriteLine("Error unknown stream table: " + type);
					throw new CLELParserException("Error unknown stream table: "+ type);
			}
			return st;
		}

		private StreamTable ReadTypeSpecTable(int [] num_rows,ref int next)
		{
			TypeSpecTable ts = new TypeSpecTable();
			int i;
			int rows = num_rows[StreamTable.TYPESPEC_TABLE];
			int signature = 0;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				ts.Add(new TypeSpecTableRow(signature));
			}
			return ts;
		}

		private StreamTable ReadAssemblyOSTable(int [] num_rows,ref int next)
		{
			AssemblyOSTable aos = new AssemblyOSTable();

			int i;
			int rows = num_rows[StreamTable.ASSEMBLYOS_TABLE];
			int os_platform_id,os_major_version,os_minor_version;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					os_platform_id = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					os_major_version = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
					os_minor_version = Endiness.IntLittleToBigEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
					next += 12;
				}
				else
				{
					os_platform_id = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					os_major_version = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
					os_minor_version = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
					next += 12;
				}
				aos.Add(new AssemblyOSTableRow(os_platform_id,os_major_version,os_minor_version));
			}

			return aos;
		}

		private StreamTable ReadAssemblyProcessorTable(int [] num_rows,ref int next)
		{
			AssemblyProcessorTable ap = new AssemblyProcessorTable();

			int i;
			int rows = num_rows[StreamTable.ASSEMBLYPROCESSOR_TABLE];
			int processor;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					processor = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
				}
				else
				{
					processor = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
				}
				ap.Add(new AssemblyProcessorTableRow(processor));
			}

			return ap;
		}
		
		private StreamTable ReadAssemblyRefOSTable(int [] num_rows,ref int next)
		{
			AssemblyRefOSTable aros = new AssemblyRefOSTable();

			int i;
			int rows = num_rows[StreamTable.ASSEMBLYREFOS_TABLE];
			int assemblyref_rows = num_rows[StreamTable.ASSEMBLYREF_TABLE];
			int os_platform_id,os_major_version,os_minor_version,assemblyref;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					os_platform_id = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					os_major_version = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
					os_minor_version = Endiness.IntLittleToBigEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
					next += 12;
					if(assemblyref_rows < 0xffff)
					{
						assemblyref = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						assemblyref = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					os_platform_id = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					os_major_version = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
					os_minor_version = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
					next += 12;
					if(assemblyref_rows < 0xffff)
					{
						assemblyref = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						assemblyref = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				aros.Add(new AssemblyRefOSTableRow(os_platform_id,os_major_version,os_minor_version,assemblyref));
			}
			return aros;
		}

		private StreamTable ReadAssemblyRefProcessorTable(int [] num_rows,ref int next)
		{
			AssemblyRefProcessorTable arp = new AssemblyRefProcessorTable();

			int i;
			int rows = num_rows[StreamTable.ASSEMBLYREFPROCESSOR_TABLE];
			int assemblyref_rows = num_rows[StreamTable.ASSEMBLYREF_TABLE];
			int processor,assemblyref;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					processor = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(assemblyref_rows < 0xffff)
					{
						assemblyref = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						assemblyref = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					processor = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(assemblyref_rows < 0xffff)
					{
						assemblyref = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						assemblyref = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				arp.Add(new AssemblyRefProcessorTableRow(processor,assemblyref));
			}
			return arp;
		}

		private StreamTable ReadClassLayoutTable(int [] num_rows,ref int next)
		{
			ClassLayoutTable cl = new ClassLayoutTable();

			int i;
			int rows = num_rows[StreamTable.CLASSLAYOUT_TABLE];
			int typedef_rows = num_rows[StreamTable.TYPEDEF_TABLE];
			short packing_size;
			int class_size,parent;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					packing_size = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					class_size = Endiness.IntLittleToBigEndian(_buffer[next+2],_buffer[next+3],_buffer[next+4],_buffer[next+5]);
					next += 6;
					if(typedef_rows < 0xffff)
					{
						parent = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						parent = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					packing_size = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					class_size = Endiness.IntBigToLittleEndian(_buffer[next+2],_buffer[next+3],_buffer[next+4],_buffer[next+5]);
					next += 6;
					if(typedef_rows < 0xffff)
					{
						parent = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						parent = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				cl.Add(new ClassLayoutTableRow(packing_size,class_size,parent));
			}
			return cl;
		}

		private StreamTable ReadConstantTable(int [] num_rows,ref int next)
		{
			ConstantTable c = new ConstantTable();

			int i;
			int rows = num_rows[StreamTable.CONSTANT_TABLE];
			short type;
			Token parent;
			int values;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					type = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					parent = TokenDecompressor.DecompressHasConstantToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						values = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						values = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					type = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					parent = TokenDecompressor.DecompressHasConstantToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						values = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						values = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				c.Add(new ConstantTableRow(type,parent,values));
			}
			return c;
		}

		private StreamTable ReadCustomAttributeTable(int [] num_rows,ref int next)
		{
			CustumAttributeTable ca = new CustumAttributeTable();

			int i;
			int rows = num_rows[StreamTable.CUSTUMATTRIBUTE_TABLE];
			Token parent,type;
			int values;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					parent = TokenDecompressor.DecompressHasCustomAttributeToken(num_rows,_buffer,ref next);
					type = TokenDecompressor.DecompressCustomAttributeTypeToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						values = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						values = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					parent = TokenDecompressor.DecompressHasCustomAttributeToken(num_rows,_buffer,ref next);
					type = TokenDecompressor.DecompressCustomAttributeTypeToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						values = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						values = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				ca.Add(new CustumAttributeTableRow(parent,type,values));
			}
			return ca;
		}

		private StreamTable ReadDeclSecurityTable(int [] num_rows,ref int next)
		{
			DeclSecurityTable ds = new DeclSecurityTable();

			int i;
			int rows = num_rows[StreamTable.DECLSECURITY_TABLE];
			short action;
			Token parent;
			int permission_set;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					action = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					parent = TokenDecompressor.DecompressHasDeclSecurityToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						permission_set = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						permission_set = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					action = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					parent = TokenDecompressor.DecompressHasDeclSecurityToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						permission_set = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						permission_set = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				ds.Add(new DeclSecurityTableRow(action,parent,permission_set));
			}

			return ds;
		}

		private StreamTable ReadEventTable(int [] num_rows,ref int next)
		{
			EventTable e = new EventTable();

			int i;
			int rows = num_rows[StreamTable.EVENT_TABLE];
			short event_flags;
			Token event_type;
			int name;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					event_flags = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					event_type = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
				}
				else
				{
					event_flags = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					event_type = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
				}
				e.Add(new EventTableRow(event_flags,name,event_type));
			}

			return e;
		}

		private StreamTable ReadEventMapTable(int [] num_rows,ref int next)
		{
			EventMapTable em = new EventMapTable();

			int i;
			int rows = num_rows[StreamTable.EVENTMAP_TABLE];
			int typedef_rows = num_rows[StreamTable.TYPEDEF_TABLE];
			int event_rows = num_rows[StreamTable.EVENT_TABLE];
			int parent,event_list;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(typedef_rows < 0xffff)
					{
						parent = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						parent = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(event_rows < 0xffff)
					{
						event_list = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						event_list = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					if(typedef_rows < 0xffff)
					{
						parent = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						parent = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(event_rows < 0xffff)
					{
						event_list = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						event_list = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				em.Add(new EventMapTableRow(parent,event_list));
			}

			return em;
		}

		private StreamTable ReadExportedTypeTable(int [] num_rows,ref int next)
		{
			ExportedTypeTable et = new ExportedTypeTable();

			int i;
			int rows = num_rows[StreamTable.EXPORTEDTYPE_TABLE];
			int flags,type_def_id,type_name,type_namespace;
			Token implementation;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					flags = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					type_def_id = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(_strings_size < 0xffff)
					{
						type_name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						type_namespace = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						type_name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						type_namespace = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
					implementation = TokenDecompressor.DecompressImplementationToken(num_rows,_buffer,ref next);
				}
				else
				{
					flags = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					type_def_id = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(_strings_size < 0xffff)
					{
						type_name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						type_namespace = (int)Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						type_name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						type_namespace = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
					implementation = TokenDecompressor.DecompressImplementationToken(num_rows,_buffer,ref next);
				}
				et.Add(new ExportedTypeTableRow(flags,type_def_id,type_name,type_namespace,implementation));
			}

			return et;
		}

		private StreamTable ReadFieldTable(int [] num_rows,ref int next)
		{
			FieldTable f = new FieldTable();

			int i;
			int rows = num_rows[StreamTable.FIELD_TABLE];
			short flags;
			int name,signature;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					flags = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					flags = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				f.Add(new FieldTableRow(flags,name,signature));
			}

			return f;
		}

		private StreamTable ReadFieldLayoutTable(int [] num_rows,ref int next)
		{
			FieldLayoutTable fl = new FieldLayoutTable();

			int i;
			int rows = num_rows[StreamTable.FIELDLAYOUT_TABLE];
			int field_rows = num_rows[StreamTable.FIELD_TABLE];	
			int offset,field;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					offset = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(field_rows < 0xffff)
					{
						field = (int)Endiness.ShortLittleToBigEndian(_buffer[next+1],_buffer[next+1]);
						next += 2;
					}
					else
					{
						field = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					offset = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(field_rows < 0xffff)
					{
						field = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						field = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				fl.Add(new FieldLayoutTableRow(offset,field));
			}

			return fl;
		}

		private StreamTable ReadFieldMarshalTable(int [] num_rows,ref int next)
		{
			FieldMarshalTable fm = new FieldMarshalTable();

			int i;
			int rows = num_rows[StreamTable.FIELDMARSHAL_TABLE];
			Token parent;
			int native_type;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					parent = TokenDecompressor.DecompressHasFieldMarshallToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						native_type = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						native_type = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					parent = TokenDecompressor.DecompressHasFieldMarshallToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						native_type = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						native_type = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				fm.Add(new FieldMarshalTableRow(parent,native_type));
			}

			return fm;
		}

		private StreamTable ReadFieldRVATable(int [] num_rows,ref int next)
		{
			FieldRVATable fr = new FieldRVATable();

			int i;
			int rows = num_rows[StreamTable.FIELDRVA_TABLE];
			int field_rows = num_rows[StreamTable.FIELD_TABLE];	
			int rva,field;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					rva = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(field_rows < 0xffff)
					{
						field = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						field = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					rva = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(field_rows < 0xffff)
					{
						field = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						field = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}

				fr.Add(new FieldRVATableRow(rva,field));
			}

			return fr;
		}

		private StreamTable ReadFileTable(int [] num_rows,ref int next)
		{
			FileTable f = new FileTable();

			int i;
			int rows = num_rows[StreamTable.FILE_TABLE];
			int flags,name,hash_value;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					flags = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						hash_value = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						hash_value = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					flags = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					next += 4;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						hash_value = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						hash_value = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				f.Add(new FileTableRow(flags,name,hash_value));
			}

			return f;
		}

		private StreamTable ReadGenericParamTable(int [] num_rows,ref int next)
		{
			GenericParamTable gp = new GenericParamTable();

			int i;
			int rows = num_rows[StreamTable.GENERICPARAM_TABLE];
			short number, flags;
			Token owner;
			int name;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					number = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					flags = Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
					next += 4;
					owner = TokenDecompressor.DecompressTypeOrMethodDefToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					number = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					flags = Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
					next += 4;
					owner = TokenDecompressor.DecompressTypeOrMethodDefToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				gp.Add(new GenericParamTableRow(number,flags,owner,name));
			}

			return gp;
		}

		private StreamTable ReadGenericParamConstraintTable(int [] num_rows,ref int next)
		{
			GenericParamConstraintTable gpc = new GenericParamConstraintTable();

			int i;
			int rows = num_rows[StreamTable.GENERICPARAMCONSTRAINT_TABLE];
			int genericparam_rows = num_rows[StreamTable.GENERICPARAM_TABLE];	
			int owner;
			Token constraint;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(genericparam_rows < 0xffff)
					{
						owner = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						owner = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					constraint = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
				}
				else
				{
					if(genericparam_rows < 0xffff)
					{
						owner = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						owner = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					constraint = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
				}
				gpc.Add(new GenericParamConstraintTableRow(owner,constraint));
			}

			return gpc;
		}

		private StreamTable ReadImplMapTable(int [] num_rows,ref int next)
		{
			ImplMapTable im = new ImplMapTable();

			int i;
			int rows = num_rows[StreamTable.IMPLMAP_TABLE];
			int moduleref_rows = num_rows[StreamTable.MODULEREF_TABLE];	
			short mapping_flags;
			Token member_forwarded;
			int import_name,import_scope;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					mapping_flags = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					member_forwarded = TokenDecompressor.DecompressMemberForwardedToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						import_name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						import_name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(moduleref_rows < 0xffff)
					{
						import_scope = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						import_scope = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					mapping_flags = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					member_forwarded = TokenDecompressor.DecompressMemberForwardedToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						import_name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						import_name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(moduleref_rows < 0xffff)
					{
						import_scope = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						import_scope = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				im.Add(new ImplMapTableRow(mapping_flags,member_forwarded,
					import_name,import_scope));
			}

			return im;
		}

		private StreamTable ReadInterfaceImplTable(int [] num_rows,ref int next)
		{
			InterfaceImplTable ii = new InterfaceImplTable();

			int i;
			int rows = num_rows[StreamTable.INTERFACEIMPL_TABLE];
			int typedef_rows = num_rows[StreamTable.TYPEDEF_TABLE];	
			int classes;
			Token interfaces;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(typedef_rows < 0xffff)
					{
						classes = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						classes = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					interfaces = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
				}
				else
				{
					if(typedef_rows < 0xffff)
					{
						classes = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						classes = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					interfaces = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
				}
				ii.Add(new InterfaceImplTableRow(classes,interfaces));
			}

			return ii;
		}

		private StreamTable ReadManifestResourceTable(int [] num_rows,ref int next)
		{
			ManifestResourceTable mr = new ManifestResourceTable();

			int i;
			int rows = num_rows[StreamTable.MANIFESTRESOURCE_TABLE];
			int offset,flags,name;
			Token implementation;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					offset = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					flags = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
					next += 8;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					implementation = TokenDecompressor.DecompressImplementationToken(num_rows,_buffer,ref next);
				}
				else
				{
					offset = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					flags = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
					next += 8;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					implementation = TokenDecompressor.DecompressImplementationToken(num_rows,_buffer,ref next);
				}
				mr.Add(new ManifestResourceTableRow(offset,flags,name,implementation));
			}

			return mr;
		}

		private StreamTable ReadMethodImplTable(int [] num_rows,ref int next)
		{
			MethodImplTable mi = new MethodImplTable();

			int i;
			int rows = num_rows[StreamTable.METHODIMPL_TABLE];
			int typedef_rows = num_rows[StreamTable.TYPEDEF_TABLE];
			int classes;
			Token method_body,method_declaration;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(typedef_rows < 0xffff)
					{
						classes = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						classes = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					method_body = TokenDecompressor.DecompressMethodDefOrRefToken(num_rows,_buffer,ref next);
					method_declaration = TokenDecompressor.DecompressMethodDefOrRefToken(num_rows,_buffer,ref next);
				}
				else
				{
					if(typedef_rows < 0xffff)
					{
						classes = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						classes = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					method_body = TokenDecompressor.DecompressMethodDefOrRefToken(num_rows,_buffer,ref next);
					method_declaration = TokenDecompressor.DecompressMethodDefOrRefToken(num_rows,_buffer,ref next);
				}
				mi.Add(new MethodImplTableRow(classes,method_body,method_declaration));
			}

			return mi;
		}

		private StreamTable ReadMethodSemanticsTable(int [] num_rows,ref int next)
		{
			MethodSemanticsTable ms = new MethodSemanticsTable();

			int i;
			int rows = num_rows[StreamTable.METHODSEMANTICS_TABLE];
			int methoddef_rows = num_rows[StreamTable.METHODDEF_TABLE];
			short semantics;
			Token association;
			int method;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					semantics = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(methoddef_rows < 0xffff)
					{
						method = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						method = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					association = TokenDecompressor.DecompressHasSemanticsToken(num_rows,_buffer,ref next);
				}
				else
				{
					semantics = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(methoddef_rows < 0xffff)
					{
						method = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						method = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					association = TokenDecompressor.DecompressHasSemanticsToken(num_rows,_buffer,ref next);
				}
				ms.Add(new MethodSemanticsTableRow(semantics,method,association));
			}

			return ms;
		}

		private StreamTable ReadMethodSpecTable(int [] num_rows,ref int next)
		{
			MethodSpecTable ms = new MethodSpecTable();

			int i;
			int rows = num_rows[StreamTable.METHODSPEC_TABLE];
			Token method;
			int instanitation;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					method = TokenDecompressor.DecompressMethodDefOrRefToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						instanitation = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						instanitation = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					method = TokenDecompressor.DecompressMethodDefOrRefToken(num_rows,_buffer,ref next);
					if(_blob_size < 0xffff)
					{
						instanitation = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						instanitation = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				ms.Add(new MethodSpecTableRow(method,instanitation));
			}

			return ms;
		}

		private StreamTable ReadModuleRefTable(int [] num_rows,ref int next)
		{
			ModuleRefTable mr = new ModuleRefTable();

			int i;
			int rows = num_rows[StreamTable.MODULEREF_TABLE];
			int name;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				mr.Add(new ModuleRefTableRow(name));
			}

			return mr;
		}
		
		private StreamTable ReadNestedClassTable(int [] num_rows,ref int next)
		{
			NestedClassTable nc = new NestedClassTable();

			int i;
			int rows = num_rows[StreamTable.NESTEDCLASS_TABLE];
			int typedef_rows = num_rows[StreamTable.TYPEDEF_TABLE];
			int nested_class,enclosing_class;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(typedef_rows < 0xffff)
					{
						nested_class = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						enclosing_class = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						nested_class = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						enclosing_class = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				else
				{
					if(typedef_rows < 0xffff)
					{
						nested_class = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						enclosing_class = (int)Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						nested_class = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						enclosing_class = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				nc.Add(new NestedClassTableRow(nested_class,enclosing_class));
			}

			return nc;
		}
		
		private StreamTable ReadPropertyTable(int [] num_rows,ref int next)
		{
			PropertyTable p = new PropertyTable();

			int i;
			int rows = num_rows[StreamTable.PROPERTY_TABLE];
			short flags;
			int name,type;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					flags = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						type = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						type = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					flags = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					next += 2;
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						type = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						type = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				p.Add(new PropertyTableRow(flags,name,type));
			}

			return p;
		}

		private StreamTable ReadPropertyMapTable(int [] num_rows,ref int next)
		{
			PropertyMapTable pm = new PropertyMapTable();

			int i;
			int rows = num_rows[StreamTable.PROPERTYMAP_TABLE];
			int typedef_rows = num_rows[StreamTable.TYPEDEF_TABLE];
			int property_rows = num_rows[StreamTable.PROPERTY_TABLE];
			int parent,property_list;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(typedef_rows < 0xffff)
					{
						parent = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						parent = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(property_rows < 0xffff)
					{
						property_list = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						property_list = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					if(typedef_rows < 0xffff)
					{
						parent = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						parent = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(property_rows < 0xffff)
					{
						property_list = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						property_list = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				pm.Add(new PropertyMapTableRow(parent,property_list));
			}

			return pm;
		}

		private StreamTable ReadAssemblyRefTable(int [] num_rows,ref int next)
		{
			AssemblyRefTable ar = new AssemblyRefTable();

			int i;
			int rows = num_rows[StreamTable.ASSEMBLYREF_TABLE];
			short majorversion,minorversion,buildnumber,revisionnumber;
			int flags,publickeyortoken,name,culture,hashvalue;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					majorversion = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					minorversion = Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
					buildnumber = Endiness.ShortLittleToBigEndian(_buffer[next+4],_buffer[next+5]);
					revisionnumber = Endiness.ShortLittleToBigEndian(_buffer[next+6],_buffer[next+7]);
					flags = Endiness.IntLittleToBigEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
					if(_blob_size < 0xffff)
					{
						publickeyortoken = (int)Endiness.ShortLittleToBigEndian(_buffer[next+12],_buffer[next+13]);
						next += 14;
					}
					else
					{
						publickeyortoken = Endiness.IntLittleToBigEndian(_buffer[next+12],_buffer[next+13],_buffer[next+14],_buffer[next+15]);
						next += 16;
					}
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						culture = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						culture = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
					if(_blob_size < 0xffff)
					{
						hashvalue = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						hashvalue = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					majorversion = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					minorversion = Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
					buildnumber = Endiness.ShortBigToLittleEndian(_buffer[next+4],_buffer[next+5]);
					revisionnumber = Endiness.ShortBigToLittleEndian(_buffer[next+6],_buffer[next+7]);
					flags = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
					if(_blob_size < 0xffff)
					{
						publickeyortoken = (int)Endiness.ShortBigToLittleEndian(_buffer[next+12],_buffer[next+13]);
						next += 14;
					}
					else
					{
						publickeyortoken = Endiness.IntBigToLittleEndian(_buffer[next+12],_buffer[next+13],_buffer[next+14],_buffer[next+15]);
						next += 16;
					}
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						culture = (int)Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						culture = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
					if(_blob_size < 0xffff)
					{
						hashvalue = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						hashvalue = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				ar.Add(new AssemblyRefTableRow(majorversion,minorversion,buildnumber,revisionnumber,
					flags,publickeyortoken,name,culture,hashvalue));
			}

			return ar;
		}

		private StreamTable ReadAssemblyTable(int [] num_rows,ref int next)
		{
			AssemblyTable a = new AssemblyTable();

			int i;
			int rows = num_rows[StreamTable.ASSEMBLY_TABLE];
			int hashalgid,flags,publickey,name,culture;
			short majorversion,minorversion,buildnumber,revisionnumber;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					hashalgid = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					majorversion = Endiness.ShortLittleToBigEndian(_buffer[next+4],_buffer[next+5]);
					minorversion = Endiness.ShortLittleToBigEndian(_buffer[next+6],_buffer[next+7]);
					buildnumber = Endiness.ShortLittleToBigEndian(_buffer[next+8],_buffer[next+9]);
					revisionnumber = Endiness.ShortLittleToBigEndian(_buffer[next+10],_buffer[next+11]);
					flags = Endiness.IntLittleToBigEndian(_buffer[next+12],_buffer[next+13],_buffer[next+14],_buffer[next+15]);
					if(_blob_size < 0xffff)
					{
						publickey = (int)Endiness.ShortLittleToBigEndian(_buffer[next+16],_buffer[next+17]);
						next += 18;
					}
					else
					{
						publickey = Endiness.IntLittleToBigEndian(_buffer[next+16],_buffer[next+17],_buffer[next+18],_buffer[next+19]);
						next += 20;
					}
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						culture = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						culture = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				else
				{
					hashalgid = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					majorversion = Endiness.ShortBigToLittleEndian(_buffer[next+4],_buffer[next+5]);
					minorversion = Endiness.ShortBigToLittleEndian(_buffer[next+6],_buffer[next+7]);
					buildnumber = Endiness.ShortBigToLittleEndian(_buffer[next+8],_buffer[next+9]);
					revisionnumber = Endiness.ShortBigToLittleEndian(_buffer[next+10],_buffer[next+11]);
					flags = Endiness.IntBigToLittleEndian(_buffer[next+12],_buffer[next+13],_buffer[next+14],_buffer[next+15]);
					if(_blob_size < 0xffff)
					{
						publickey = (int)Endiness.ShortBigToLittleEndian(_buffer[next+16],_buffer[next+17]);
						next += 18;
					}
					else
					{
						publickey = Endiness.IntBigToLittleEndian(_buffer[next+16],_buffer[next+17],_buffer[next+18],_buffer[next+19]);
						next += 20;
					}
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						culture = (int)Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						culture = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				a.Add(new AssemblyTableRow(hashalgid,majorversion,minorversion,buildnumber,revisionnumber,
					flags,publickey,name,culture));
			}

			return a;
		}

		private StreamTable ReadStandAloneSigTable(int [] num_rows,ref int next)
		{
			StandAloneSigTable sas = new StandAloneSigTable();

			int i;
			int rows = num_rows[StreamTable.STANDALONESIG_TABLE];
			int signature;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					if(_blob_size <  0xffff)
					{
						signature = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				sas.Add(new StandAloneSigTableRow(signature));
			}

			return sas;
		}

		private StreamTable ReadMemberRefTable(int [] num_rows,ref int next)
		{
			MemberRefTable mr = new MemberRefTable();

			int i;
			int rows = num_rows[StreamTable.MEMBERREF_TABLE];
			Token classes;
			int name,signature;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					classes = TokenDecompressor.DecompressMemberRefParentToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					classes = TokenDecompressor.DecompressMemberRefParentToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				mr.Add(new MemberRefTableRow(classes,name,signature));
			}

			return mr;
		}

		private StreamTable ReadParamTable(int [] num_rows,ref int next)
		{
			ParamTable pt = new ParamTable();

			int i;
			int rows = num_rows[StreamTable.PARAM_TABLE];
			short flags,sequence;
			int name;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					flags = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					sequence = Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next+4],_buffer[next+5]);
						next += 6;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				else
				{
					flags = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					sequence = Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next+4],_buffer[next+5]);
						next += 6;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				pt.Add(new ParamTableRow(flags,sequence,name));
			}

			return pt;
		}

		private StreamTable ReadMethodDefTable(int [] num_rows,ref int next)
		{
			MethodDefTable md = new MethodDefTable();

			int rva,name,signature,paramlist;
			short implflags,flags;
			int i;
			int rows = num_rows[StreamTable.METHODDEF_TABLE];
			int param_rows = num_rows[StreamTable.PARAM_TABLE];
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					rva = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					implflags = Endiness.ShortLittleToBigEndian(_buffer[next+4],_buffer[next+5]);
					flags = Endiness.ShortLittleToBigEndian(_buffer[next+6],_buffer[next+7]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next+8],_buffer[next+9]);
						next += 10;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 12;
					}
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(param_rows < 0xffff)
					{
						paramlist = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						paramlist = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					rva = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					implflags = Endiness.ShortBigToLittleEndian(_buffer[next+4],_buffer[next+5]);
					flags = Endiness.ShortBigToLittleEndian(_buffer[next+6],_buffer[next+7]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next+8],_buffer[next+9]);
						next += 10;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 12;
					}
					if(_blob_size < 0xffff)
					{
						signature = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						signature = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(param_rows < 0xffff)
					{
						paramlist = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						paramlist = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				md.Add(new MethodDefTableRow(rva,implflags,flags,name,signature,paramlist));
			}

			return md;
		}

		private StreamTable ReadTypeRefTable(int [] num_rows,ref int next)
		{
			TypeRefTable tr = new TypeRefTable();

			int i;
			int rows = num_rows[StreamTable.TYPEREF_TABLE];
			Token resolutionscope;
			int name,namespaces;
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					resolutionscope = TokenDecompressor.DecompressResolutionScopeToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						namespaces = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						namespaces = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
				}
				else
				{
					resolutionscope = TokenDecompressor.DecompressResolutionScopeToken(num_rows,_buffer,ref next);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						namespaces = (int)Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						namespaces = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						next += 9;
					}
				}
				tr.Add(new TypeRefTableRow(resolutionscope,name,namespaces));
			}

			return tr;
		}

		private StreamTable ReadTypeDefTable(int [] num_rows,ref int next)
		{
			TypeDefTable td = new TypeDefTable();

			Token extend;
			int flags,name,namespaces,fieldlist,methodlist;
			int i;
			int rows = num_rows[StreamTable.TYPEDEF_TABLE];
			int methoddef_rows = num_rows[StreamTable.METHODDEF_TABLE];
			int field_rows = num_rows[StreamTable.FIELD_TABLE];
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					flags = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next+4],_buffer[next+5]);
						namespaces = (int)Endiness.ShortLittleToBigEndian(_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						namespaces = Endiness.IntLittleToBigEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 12;
					}
					extend = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
					if(field_rows < 0xffff)
					{
						fieldlist = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						fieldlist = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(methoddef_rows < 0xffff)
					{
						methodlist = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						methodlist = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
				}
				else
				{
					flags = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortBigToLittleEndian(_buffer[next+4],_buffer[next+5]);
						namespaces = (int)Endiness.ShortBigToLittleEndian(_buffer[next+6],_buffer[next+7]);
						next += 8;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						namespaces = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 12;
					}
					extend = TokenDecompressor.DecompressTypeDefOrRefToken(num_rows,_buffer,ref next);
					if(field_rows < 0xffff)
					{
						fieldlist = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						next += 2;
					}
					else
					{
						fieldlist = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					if(methoddef_rows < 0xffff)
					{
						methodlist = (int)Endiness.ShortBigToLittleEndian(_buffer[next+6],_buffer[next+7]);	
						next += 2;
					}
					else
					{
						methodlist = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 4;
					}
				}
				td.Add(new TypeDefTableRow(flags,name,namespaces,extend,fieldlist,methodlist));
			}

			return td;
		}

		private StreamTable ReadModuleTable(int [] num_rows,ref int next)
		{
			ModuleTable mt = new ModuleTable();

			int i;
			short generation;
			int name,mvid,encld,encbaseid;
			int rows = num_rows[StreamTable.MODULE_TABLE];
			for(i = 0;i < rows;i++)
			{
				if(_little_endian)
				{
					generation = Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
					if(_strings_size < 0xffff)
					{
						name = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntLittleToBigEndian(_buffer[next+2],_buffer[next+3],_buffer[next+4],_buffer[next+5]);
						next += 6;
					}
					if(_guid_size < 0xffff)
					{
						mvid = (int)Endiness.ShortLittleToBigEndian(_buffer[next],_buffer[next+1]);
						encld = (int)Endiness.ShortLittleToBigEndian(_buffer[next+2],_buffer[next+3]);
						encbaseid = (int)Endiness.ShortLittleToBigEndian(_buffer[next+4],_buffer[next+5]);
						next += 6;
					}
					else
					{
						mvid = Endiness.IntLittleToBigEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						encld = Endiness.IntLittleToBigEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						encbaseid = Endiness.IntLittleToBigEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 12;
					}
				}
				else
				{
					generation = Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
					if(_strings_size < 0xffff)
					{
						name = Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						next += 4;
					}
					else
					{
						name = Endiness.IntBigToLittleEndian(_buffer[next+2],_buffer[next+3],_buffer[next+4],_buffer[next+5]);
						next += 6;
					}
					if(_guid_size < 0xffff)
					{
						mvid = (int)Endiness.ShortBigToLittleEndian(_buffer[next],_buffer[next+1]);
						encld = (int)Endiness.ShortBigToLittleEndian(_buffer[next+2],_buffer[next+3]);
						encbaseid = (int)Endiness.ShortBigToLittleEndian(_buffer[next+4],_buffer[next+5]);
						next += 6;
					}
					else
					{
						mvid = Endiness.IntBigToLittleEndian(_buffer[next],_buffer[next+1],_buffer[next+2],_buffer[next+3]);
						encld = Endiness.IntBigToLittleEndian(_buffer[next+4],_buffer[next+5],_buffer[next+6],_buffer[next+7]);
						encbaseid = Endiness.IntBigToLittleEndian(_buffer[next+8],_buffer[next+9],_buffer[next+10],_buffer[next+11]);
						next += 12;
					}
				}
				mt.Add(new ModuleTableRow(generation,name,mvid,encld,encbaseid));
			}

			return mt;
		}

		private void ParseFieldDefaultValues()
		{
			FieldRVATable fr = (FieldRVATable)_text.PoundTildaStream.Tables[StreamTable.FIELDRVA_TABLE];
			if(fr != null)
			{
				int fieldrva_count = fr.Count;
				FieldRVATableRow frva_row;
			
				FieldTable f = (FieldTable)_text.PoundTildaStream.Tables[StreamTable.FIELD_TABLE];
				int field_count = 0;
				if(f != null)
					field_count = f.Count;
				FieldTableRow f_row;
			
				ClassLayoutTable cl = (ClassLayoutTable)_text.PoundTildaStream.Tables[StreamTable.CLASSLAYOUT_TABLE];
				int class_layout_count = 0;
				if(cl != null)
					class_layout_count = cl.Count;
				ClassLayoutTableRow cl_row;
			
				int i,j,k;
				int field,rva;
				int default_offset;
				int size;
				byte[] default_value;
				Blob signature;
				FieldBlobInfo info;
				ClassDescriptor cd;
				BuiltInClassDescriptor bicd;
				TypeDefClassDescriptor tdcd;
				//TypeRefClassDescriptor trcd;
				int type;
				int row;
				for(i = 0;i < fieldrva_count;i++)
				{
					frva_row = fr.Get(i);
					field = frva_row.Field;
					rva = frva_row.RVA;
					if((field > 0) && (field <= field_count) && rva > 0)
					{
						f_row = f.Get(field-1);
						default_offset = rva-_rva;
						signature = _text.BlobStream.Get(f_row.Signature);
						if(signature != null)
						{
							info = new FieldBlobInfo(signature.BlobValue,_asm);
							cd = info.Type.FieldType;
							if(cd != null)
							{
								size = 0;
								if(cd.Type == ClassDescriptor.BUILTIN_CLASSDESCRIPTOR)
								{
									bicd = (BuiltInClassDescriptor)cd;
									type = bicd.BuiltInType;
									//TODO: ADD REST OF TYPES
									if(type == BlobElementType.ELEMENT_TYPE_I4)
										size = 4;
								}
								else if(cd.Type == ClassDescriptor.TYPEDEF_CLASSDESCRIPTOR)
								{
									tdcd = (TypeDefClassDescriptor)cd;
									row = tdcd.ClassToken.Row;
									for(j = 0;j < class_layout_count;j++)
									{
										cl_row = cl.Get(j);
										if(cl_row.Parent == row)
										{
											size = cl_row.ClassSize;
											break;
										}
									}
									//TODO: ??????? is size always in ClassLayout?
								}
								else if(cd.Type == ClassDescriptor.TYPEREF_CLASSDESCRIPTOR)
								{
									//TODO
									//trcd = (TypeRefClassDescriptor)cd;
								}
				
								if(size <= 0)
									throw new CLELParserException("Error reading size of default value for field");

								//TODO: SAVE FIELD DEFAULT VALUE
								default_value = new byte[size];
								for(k = 0;k < size;k++)
									default_value[k] = _buffer[default_offset+k];
								frva_row.DefaultValue = default_value;
							}
						}
					}
				}
			}
		}

		private void ParseStringStream()
		{
			DataDirectory metadata_dd = _text.CLIHeader.Metadata;
			int metadata_offset = metadata_dd.VirtualAddress;

			StreamHeader strings_sh = _text.StreamHeaders.GetStreamHeader(StreamHeader.STRINGS_NAME);
			if(strings_sh == null)
				return;
			int off = metadata_offset-_rva+strings_sh.Offset;
			int size = strings_sh.Size;
			if(off < 0 || off+size >= _buffer.Length)
			{
				_log.WriteLine("Error strings stream out of bounds: " + off);
				throw new CLELParserException("Error strings stream out of bounds: "+ off);
			}

			StringsStream strings = new StringsStream();

			int i;
			byte next;
			byte [] bytes;
			ASCIIEncoding encoding = new ASCIIEncoding();
			StringBuilder str = new StringBuilder();
			//remove
			//int start = 0;
			for(i = 0;i < size;i++)
			{
				next = _buffer[off+i];
				str.Append((char)next);
				if(next == 0x0)
				{
					//remove
					//Console.WriteLine(start+ " " + str.ToString());
					//if(i == 0)
					//	start = 1;
					//else
					//	start = i;
					bytes = encoding.GetBytes(str.ToString());
					strings.Add(bytes);
					str = new StringBuilder();
				}
			}

			_text.StringsStream = strings;
		}

		private void ParseGUIDStream()
		{
			DataDirectory metadata_dd = _text.CLIHeader.Metadata;
			int metadata_offset = metadata_dd.VirtualAddress;

			StreamHeader guid_sh = _text.StreamHeaders.GetStreamHeader(StreamHeader.GUID_NAME);
			if(guid_sh == null)
				return;
			int off = metadata_offset-_rva+guid_sh.Offset;
			int size = guid_sh.Size;
			if(off < 0 || off+size >= _buffer.Length)
			{
				_log.WriteLine("Error guid stream out of bounds: " + off);
				throw new CLELParserException("Error guid stream out of bounds: "+ off);
			}

			GUIDStream guids = new GUIDStream();
			
			int i,j;
			int guid_size = GUID.GUID_SIZE;
			byte [] guid;
			for(i = 0;i < size;i += guid_size)
			{
				guid = new byte[guid_size];
				for(j = 0;j < guid_size;j++)
					guid[j] = _buffer[off+i+j];
				guids.Add(guid);
			}

			_text.GUIDStream = guids;
		}

		private void ParseBlobStream()
		{
			DataDirectory metadata_dd = _text.CLIHeader.Metadata;
			int metadata_offset = metadata_dd.VirtualAddress;

			StreamHeader blob_sh = _text.StreamHeaders.GetStreamHeader(StreamHeader.BLOB_NAME);
			if(blob_sh == null)
				return;
			int off = metadata_offset-_rva+blob_sh.Offset;
			int size = blob_sh.Size;
			if(off < 0 || off+size >= _buffer.Length)
			{
				_log.WriteLine("Error blob stream out of bounds: " + off);
				throw new CLELParserException("Error blob stream out of bounds: "+ off);
			}

			BlobStream blobs = new BlobStream();
	
			int stop = off+size;
			Blob blob;
			while(off < stop)
			{
				blob = Blob.ParseBlob(_buffer,off);
				off += blob.Length;
				blobs.Add(blob);
			}

			_text.BlobStream = blobs;
		}

		private void ParseUSStream()
		{
			DataDirectory metadata_dd = _text.CLIHeader.Metadata;
			int metadata_offset = metadata_dd.VirtualAddress;

			StreamHeader us_sh = _text.StreamHeaders.GetStreamHeader(StreamHeader.US_NAME);
			if(us_sh == null)
				return;
			int off = metadata_offset-_rva+us_sh.Offset;
			int size = us_sh.Size;
			if(off < 0 || off+size >= _buffer.Length)
			{
				_log.WriteLine("Error us stream out of bounds: " + off);
				throw new CLELParserException("Error us stream out of bounds: "+ off);
			}

			USStream us = new USStream();
		
			/*	
			int us_size;
			byte [] bytes;
			int i;
			int stop = off + size;
			while(off < stop)
			{
				us_size = (int)Endiness.ShortBigToLittleEndian(_buffer[off],_buffer[off+1]);
				off += 2;

				if(us_size > 0)
				{
					bytes = new byte[us_size];
					for(i = 0;i < us_size;i++)
					{
						bytes[i] = _buffer[off+i];
					}
					off += us_size;
					us.Add(bytes);
				}
			}
			*/
			int stop = off+size;
			Blob blob;
			while(off < stop)
			{
				blob = Blob.ParseBlob(_buffer,off);
				off += blob.Length;
				us.Add(blob.BlobValue);
			}

			_text.USStream = us;
		}

		private void ParseMethodHeaders()
		{
			MethodDefTable md = (MethodDefTable)_text.PoundTildaStream.Tables[StreamTable.METHODDEF_TABLE];
			int i;
			int count = md.Count;
			MethodDefTableRow row;
			List<MethodHeader> method_headers = new List<MethodHeader>();
			for(i = 0;i < count;i++)
			{
				row = md.Get(i);
				if(row.RVA != 0)
				{
					MethodHeader mh = MethodHeader.ParseMethodHeader(_buffer,row.RVA-_rva,_little_endian);
					method_headers.Add(mh);
					row.MethodHeader = mh;
				}
				else
				{
					method_headers.Add(null);
				}
			}
			_text.MethodHeaders = method_headers;
		}

		private void ParseEntryPoint()
		{
			int entry_point_offset = _asm.StandardFields.AddressOfEntryPoint - _rva;

			if(entry_point_offset < 0 || entry_point_offset+EntryPointRVA.ENTRYPOINTRVA_SIZE >= _buffer.Length)
			{
				_log.WriteLine("Error entry point offset out of bounds: " + entry_point_offset);
				throw new CLELParserException("Error entry point offset out of bounds: "+ entry_point_offset);
			}

			EntryPointRVA entry_point_rva = new EntryPointRVA();
			if(_little_endian)
			{
				entry_point_rva.Magic = Endiness.ShortLittleToBigEndian(_buffer[entry_point_offset],_buffer[entry_point_offset+1]);
				entry_point_offset += 2;
				entry_point_rva.RVA = Endiness.IntLittleToBigEndian(_buffer[entry_point_offset],_buffer[entry_point_offset+1],_buffer[entry_point_offset+2],_buffer[entry_point_offset+3]);
			}
			else
			{
				entry_point_rva.Magic = Endiness.ShortBigToLittleEndian(_buffer[entry_point_offset],_buffer[entry_point_offset+1]);
				entry_point_offset += 2;
				entry_point_rva.RVA = Endiness.IntBigToLittleEndian(_buffer[entry_point_offset],_buffer[entry_point_offset+1],_buffer[entry_point_offset+2],_buffer[entry_point_offset+3]);
			}

			_text.EntryPointRVA = entry_point_rva;
		}

		private void ParseCLIHeader()
		{
			DataDirectory cliheader_dd = _asm.DataDirectories[DataDirectories.CLIHEADER_INDEX];
			int cliheader_offset = cliheader_dd.VirtualAddress - _rva;
			
			if(cliheader_offset < 0 || cliheader_offset+CLIHeader.CLIHEADER_SIZE >= _buffer.Length)
			{
				_log.WriteLine("Error cli header offset out of bounds: " + cliheader_offset);
				throw new CLELParserException("Error cli header offset out of bounds: "+ cliheader_offset);
			}

			CLIHeader cli_header = new CLIHeader();

			int offset;
			int size;
			if(_little_endian)
			{
				cli_header.Cb = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset],_buffer[cliheader_offset+1],_buffer[cliheader_offset+2],_buffer[cliheader_offset+3]);
				cli_header.MajorRuntimeVersion = Endiness.ShortLittleToBigEndian(_buffer[cliheader_offset+4],_buffer[cliheader_offset+5]);
				cli_header.MinorRuntimeVersion = Endiness.ShortLittleToBigEndian(_buffer[cliheader_offset+6],_buffer[cliheader_offset+7]);
				
				offset = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+8],_buffer[cliheader_offset+9],_buffer[cliheader_offset+10],_buffer[cliheader_offset+11]);
				size = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+12],_buffer[cliheader_offset+13],_buffer[cliheader_offset+14],_buffer[cliheader_offset+15]);
				cli_header.Metadata = new DataDirectory(offset,size);
				
				cli_header.Flags = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+16],_buffer[cliheader_offset+17],_buffer[cliheader_offset+18],_buffer[cliheader_offset+19]);
				cli_header.EntryPointToken = new Token(Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+20],_buffer[cliheader_offset+21],_buffer[cliheader_offset+22],_buffer[cliheader_offset+23]));
				
				offset = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+24],_buffer[cliheader_offset+25],_buffer[cliheader_offset+26],_buffer[cliheader_offset+27]);
				size = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+28],_buffer[cliheader_offset+29],_buffer[cliheader_offset+30],_buffer[cliheader_offset+31]);
				cli_header.Resources = new DataDirectory(offset,size);

				offset = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+32],_buffer[cliheader_offset+33],_buffer[cliheader_offset+34],_buffer[cliheader_offset+35]);
				size = Endiness.IntLittleToBigEndian(_buffer[cliheader_offset+36],_buffer[cliheader_offset+37],_buffer[cliheader_offset+38],_buffer[cliheader_offset+39]);
				cli_header.StrongNameSignature = new DataDirectory(offset,size);
				
				cli_header.CodeManagerTable = Endiness.LongLittleToBigEndian(_buffer[cliheader_offset+40],_buffer[cliheader_offset+41],_buffer[cliheader_offset+42],_buffer[cliheader_offset+43],_buffer[cliheader_offset+44],_buffer[cliheader_offset+45],_buffer[cliheader_offset+46],_buffer[cliheader_offset+47]);
				cli_header.VTableFixups = Endiness.LongLittleToBigEndian(_buffer[cliheader_offset+48],_buffer[cliheader_offset+49],_buffer[cliheader_offset+50],_buffer[cliheader_offset+51],_buffer[cliheader_offset+52],_buffer[cliheader_offset+53],_buffer[cliheader_offset+54],_buffer[cliheader_offset+55]);
				cli_header.ExportAddressTableJumps = Endiness.LongLittleToBigEndian(_buffer[cliheader_offset+56],_buffer[cliheader_offset+57],_buffer[cliheader_offset+58],_buffer[cliheader_offset+59],_buffer[cliheader_offset+60],_buffer[cliheader_offset+61],_buffer[cliheader_offset+62],_buffer[cliheader_offset+63]);
				cli_header.ManageNativeHeader = Endiness.LongLittleToBigEndian(_buffer[cliheader_offset+64],_buffer[cliheader_offset+65],_buffer[cliheader_offset+66],_buffer[cliheader_offset+67],_buffer[cliheader_offset+68],_buffer[cliheader_offset+69],_buffer[cliheader_offset+70],_buffer[cliheader_offset+71]);
			}
			else
			{
				cli_header.Cb = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset],_buffer[cliheader_offset+1],_buffer[cliheader_offset+2],_buffer[cliheader_offset+3]);
				cli_header.MajorRuntimeVersion = Endiness.ShortBigToLittleEndian(_buffer[cliheader_offset+4],_buffer[cliheader_offset+5]);
				cli_header.MinorRuntimeVersion = Endiness.ShortBigToLittleEndian(_buffer[cliheader_offset+6],_buffer[cliheader_offset+7]);
				
				offset = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+8],_buffer[cliheader_offset+9],_buffer[cliheader_offset+10],_buffer[cliheader_offset+11]);
				size = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+12],_buffer[cliheader_offset+13],_buffer[cliheader_offset+14],_buffer[cliheader_offset+15]);
				cli_header.Metadata = new DataDirectory(offset,size);
				
				cli_header.Flags = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+16],_buffer[cliheader_offset+17],_buffer[cliheader_offset+18],_buffer[cliheader_offset+19]);
				cli_header.EntryPointToken = new Token(Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+20],_buffer[cliheader_offset+21],_buffer[cliheader_offset+22],_buffer[cliheader_offset+23]));
				
				offset = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+24],_buffer[cliheader_offset+25],_buffer[cliheader_offset+26],_buffer[cliheader_offset+27]);
				size = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+28],_buffer[cliheader_offset+29],_buffer[cliheader_offset+30],_buffer[cliheader_offset+31]);
				cli_header.Resources = new DataDirectory(offset,size);
				
				offset = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+32],_buffer[cliheader_offset+33],_buffer[cliheader_offset+34],_buffer[cliheader_offset+35]);
				size = Endiness.IntBigToLittleEndian(_buffer[cliheader_offset+36],_buffer[cliheader_offset+37],_buffer[cliheader_offset+38],_buffer[cliheader_offset+39]);
				cli_header.StrongNameSignature = new DataDirectory(offset,size);
				
				cli_header.CodeManagerTable = Endiness.LongBigToLittleEndian(_buffer[cliheader_offset+40],_buffer[cliheader_offset+41],_buffer[cliheader_offset+42],_buffer[cliheader_offset+43],_buffer[cliheader_offset+44],_buffer[cliheader_offset+45],_buffer[cliheader_offset+46],_buffer[cliheader_offset+47]);
				cli_header.VTableFixups = Endiness.LongBigToLittleEndian(_buffer[cliheader_offset+48],_buffer[cliheader_offset+49],_buffer[cliheader_offset+50],_buffer[cliheader_offset+51],_buffer[cliheader_offset+52],_buffer[cliheader_offset+53],_buffer[cliheader_offset+54],_buffer[cliheader_offset+55]);
				cli_header.ExportAddressTableJumps = Endiness.LongBigToLittleEndian(_buffer[cliheader_offset+56],_buffer[cliheader_offset+57],_buffer[cliheader_offset+58],_buffer[cliheader_offset+59],_buffer[cliheader_offset+60],_buffer[cliheader_offset+61],_buffer[cliheader_offset+62],_buffer[cliheader_offset+63]);
				cli_header.ManageNativeHeader = Endiness.LongBigToLittleEndian(_buffer[cliheader_offset+64],_buffer[cliheader_offset+65],_buffer[cliheader_offset+66],_buffer[cliheader_offset+67],_buffer[cliheader_offset+68],_buffer[cliheader_offset+69],_buffer[cliheader_offset+70],_buffer[cliheader_offset+71]);
			}

			_text.CLIHeader = cli_header;
		}

		private void ParseStrongNameSignature()
		{
			DataDirectory strong_dd = _text.CLIHeader.StrongNameSignature;
			int strong_offset = strong_dd.VirtualAddress;
			if(strong_offset != 0)
			{
				strong_offset -= _rva;
				int size = strong_dd.Size;

				if(strong_offset < 0 || size <= 0 || strong_offset+size >= _buffer.Length)
				{
					_log.WriteLine("Error strong name signature offset out of bounds: " + strong_offset);
					throw new CLELParserException("Error strong name signature offset out of bounds: "+ strong_offset);
				}

				byte[] strong = new byte[size];
				int i;
				for(i = 0;i < size;i++)
				{
					strong[i] = _buffer[strong_offset+i];
				}

				_text.StrongNameSignature = strong;
			}
		}

		private void ParseImportTable()
		{
			DataDirectory import_dd = _asm.DataDirectories[DataDirectories.IMPORTTABLE_INDEX];
			int import_offset = import_dd.VirtualAddress - _rva;
			
			if(import_offset < 0 || import_offset+ImportTable.IMPORTTABLE_SIZE >= _buffer.Length)
			{
				_log.WriteLine("Error import table offset out of bounds: " + import_offset);
				throw new CLELParserException("Error import table offset out of bounds: "+ import_offset);
			}

			ImportTable import_table = new ImportTable();
			
			if(_little_endian)
			{
				import_table.ImportLookupTable = Endiness.IntLittleToBigEndian(_buffer[import_offset],_buffer[import_offset+1],_buffer[import_offset+2],_buffer[import_offset+3]);
				import_table.DateTimeStamp = Endiness.IntLittleToBigEndian(_buffer[import_offset+4],_buffer[import_offset+5],_buffer[import_offset+6],_buffer[import_offset+7]);
				import_table.ForwarderChain = Endiness.IntLittleToBigEndian(_buffer[import_offset+8],_buffer[import_offset+9],_buffer[import_offset+10],_buffer[import_offset+11]);
				import_table.Name = Endiness.IntLittleToBigEndian(_buffer[import_offset+12],_buffer[import_offset+13],_buffer[import_offset+14],_buffer[import_offset+15]);
				import_table.ImportAddressTable = Endiness.IntLittleToBigEndian(_buffer[import_offset+16],_buffer[import_offset+17],_buffer[import_offset+18],_buffer[import_offset+19]);
			}
			else
			{
				import_table.ImportLookupTable = Endiness.IntBigToLittleEndian(_buffer[import_offset],_buffer[import_offset+1],_buffer[import_offset+2],_buffer[import_offset+3]);
				import_table.DateTimeStamp = Endiness.IntBigToLittleEndian(_buffer[import_offset+4],_buffer[import_offset+5],_buffer[import_offset+6],_buffer[import_offset+7]);
				import_table.ForwarderChain = Endiness.IntBigToLittleEndian(_buffer[import_offset+8],_buffer[import_offset+9],_buffer[import_offset+10],_buffer[import_offset+11]);
				import_table.Name = Endiness.IntBigToLittleEndian(_buffer[import_offset+12],_buffer[import_offset+13],_buffer[import_offset+14],_buffer[import_offset+15]);
				import_table.ImportAddressTable = Endiness.IntBigToLittleEndian(_buffer[import_offset+16],_buffer[import_offset+17],_buffer[import_offset+18],_buffer[import_offset+19]);
			}

			int i;
			byte [] padding = new byte[ImportTable.PADDING_SIZE];
			int start = import_offset + (ImportTable.IMPORTTABLE_SIZE-ImportTable.PADDING_SIZE);
			for(i = 0;i < padding.Length;i++)
				padding[i] = _buffer[start+i];
			import_table.Padding = padding;

			_text.ImportTable = import_table;
		}

		private void ParseImportAddressTable()
		{
			DataDirectory importaddress_dd = _asm.DataDirectories[DataDirectories.IMPORTADDRESSTABLE_INDEX];
			int importaddress_offset = importaddress_dd.VirtualAddress - _rva;
	
			if(importaddress_offset < 0 || importaddress_offset+ImportAddressTable.IMPORTADDRESSTABLE_SIZE >= _buffer.Length)
			{
				_log.WriteLine("Error import address table offset out of bounds: " + importaddress_offset);
				throw new CLELParserException("Error import address table offset out of bounds: "+ importaddress_offset);
			}

			ImportAddressTable import_address_table = new ImportAddressTable();

			if(_little_endian)
			{
				import_address_table.NameTableRVA = Endiness.IntLittleToBigEndian(_buffer[importaddress_offset],_buffer[importaddress_offset+1],_buffer[importaddress_offset+2],_buffer[importaddress_offset+3]);
			}
			else
			{
				import_address_table.NameTableRVA = Endiness.IntBigToLittleEndian(_buffer[importaddress_offset],_buffer[importaddress_offset+1],_buffer[importaddress_offset+2],_buffer[importaddress_offset+3]);
			}
			
			int i;
			byte [] padding = new byte[ImportAddressTable.PADDING_SIZE];
			int start = importaddress_offset + (ImportAddressTable.IMPORTADDRESSTABLE_SIZE-ImportAddressTable.PADDING_SIZE);
			for(i = 0;i < padding.Length;i++)
				padding[i] = _buffer[start+i];
			import_address_table.Padding = padding;

			_text.ImportAddressTable = import_address_table;
		}

		private void ParseImportLookupTable()
		{
			int importlookup_offset = _text.ImportTable.ImportLookupTable - _rva;;
	
			if(importlookup_offset < 0 || importlookup_offset+ImportLookupTable.IMPORTLOOKUPTABLE_SIZE >= _buffer.Length)
			{
				_log.WriteLine("Error import lookup table offset out of bounds: " + importlookup_offset);
				throw new CLELParserException("Error import lookup table offset out of bounds: "+ importlookup_offset);
			}

			ImportLookupTable import_lookup_table = new ImportLookupTable();

			if(_little_endian)
			{
				import_lookup_table.NameTableRVA = Endiness.IntLittleToBigEndian(_buffer[importlookup_offset],_buffer[importlookup_offset+1],_buffer[importlookup_offset+2],_buffer[importlookup_offset+3]);
			}
			else
			{
				import_lookup_table.NameTableRVA = Endiness.IntBigToLittleEndian(_buffer[importlookup_offset],_buffer[importlookup_offset+1],_buffer[importlookup_offset+2],_buffer[importlookup_offset+3]);
			}
		
			/*	
			int i;
			byte [] padding = new byte[ImportLookupTable.PADDING_SIZE];
			int start = importlookup_offset + (ImportLookupTable.IMPORTLOOKUPTABLE_SIZE-ImportLookupTable.PADDING_SIZE-ImportLookupTable.UNDOCUMENTED_SIZE);
			for(i = 0;i < padding.Length;i++)
				padding[i] = _buffer[start+i];
			import_lookup_table.Padding = padding;

			padding = new byte[ImportLookupTable.UNDOCUMENTED_SIZE];
			start = importlookup_offset + (ImportLookupTable.IMPORTLOOKUPTABLE_SIZE-ImportLookupTable.UNDOCUMENTED_SIZE);
			for(i = 0;i < padding.Length;i++)
				padding[i] = _buffer[start+i];
			import_lookup_table.Undocumented = padding;
			*/
			_text.ImportLookupTable = import_lookup_table;
		}

		private void ParseNameTable()
		{
			int name_offset = _text.ImportAddressTable.NameTableRVA - _rva;;
	
			if(name_offset < 0 || name_offset+NameTable.NAMETABLE_SIZE >= _buffer.Length)
			{
				_log.WriteLine("Error name table offset out of bounds: " + name_offset);
				throw new CLELParserException("Error name table offset out of bounds: "+ name_offset);
			}

			NameTable name_table = new NameTable();

			if(_little_endian)
			{
				name_table.Hint = Endiness.ShortLittleToBigEndian(_buffer[name_offset],_buffer[name_offset+1]);
			}
			else
			{
				name_table.Hint = Endiness.ShortBigToLittleEndian(_buffer[name_offset],_buffer[name_offset+1]);
			}

			int i;
			byte [] name = new byte[NameTable.NAME_SIZE];
			int start = name_offset + 2;
			for(i = 0;i < name.Length;i++)
				name[i] = _buffer[start+i];
			name_table.Name1 = name;

			name = new byte[NameTable.NAME_SIZE];
			start += NameTable.NAME_SIZE;
			for(i = 0;i < name.Length;i++)
				name[i] = _buffer[start+i];
			name_table.Name2 = name;

			name = new byte[NameTable.UNDOCUMENTED_SIZE];
			start += NameTable.NAME_SIZE;
			for(i = 0;i < name.Length;i++)
				name[i] = _buffer[start+i];
			name_table.Undocumented = name;

			_text.NameTable = name_table;
		}

		private void ParseCLIResources()
		{
			DataDirectory res_dd = _text.CLIHeader.Resources;
			int va = res_dd.VirtualAddress - _rva;
			if(va >= 0)
			{
				List<CLIResource> resources = new List<CLIResource>();
				int size = res_dd.Size;
				int stop = va+size;
				int res_size;
				byte [] res_data;
				int i;
				int padding;
				CLIResource r;
				while(va < stop)
				{
					if(_little_endian)
					{
						res_size = Endiness.IntLittleToBigEndian(_buffer[va],_buffer[va+1],_buffer[va+2],_buffer[va+3]);
					}
					else
					{
						res_size = Endiness.IntBigToLittleEndian(_buffer[va],_buffer[va+1],_buffer[va+2],_buffer[va+3]);
					}
					
					va += 4;
					res_data = new byte[res_size];
					for(i = 0;i < res_size;i++)
					{
						res_data[i] = _buffer[va+i];
					}
					va += res_size;
					
					padding = 8-((res_size+4)%8);
					if(padding == 8)
						padding = 0;
					va += padding;					

					r = new CLIResource();
					r.Data = res_data;
					resources.Add(r);
				}
				_text.CLIResources = resources;
			}
		}

		private void ParseDebug()
		{
			DataDirectory debug_dd = _asm.DataDirectories[DataDirectories.DEBUG_INDEX];
			if(debug_dd.VirtualAddress > 0)
			{
				int debug_offset = debug_dd.VirtualAddress - _rva;
				DebugDirectory debug_image = new DebugDirectory();
					
				int characteristics;
				int time_date_stamp;
				short major_version;
				short minor_version;
				int type;
				int size_of_data;
				int address_of_raw_data;
				int pointer_to_raw_data;

				if(_little_endian)
				{
					characteristics = Endiness.IntLittleToBigEndian(_buffer[debug_offset],_buffer[debug_offset+1],_buffer[debug_offset+2],_buffer[debug_offset+3]);
					time_date_stamp = Endiness.IntLittleToBigEndian(_buffer[debug_offset+4],_buffer[debug_offset+5],_buffer[debug_offset+6],_buffer[debug_offset+7]);
					major_version = Endiness.ShortLittleToBigEndian(_buffer[debug_offset+8],_buffer[debug_offset+9]);
					minor_version = Endiness.ShortLittleToBigEndian(_buffer[debug_offset+10],_buffer[debug_offset+11]);
					type = Endiness.IntLittleToBigEndian(_buffer[debug_offset+12],_buffer[debug_offset+13],_buffer[debug_offset+14],_buffer[debug_offset+15]);
					size_of_data = Endiness.IntLittleToBigEndian(_buffer[debug_offset+16],_buffer[debug_offset+17],_buffer[debug_offset+18],_buffer[debug_offset+19]);
					address_of_raw_data = Endiness.IntLittleToBigEndian(_buffer[debug_offset+20],_buffer[debug_offset+21],_buffer[debug_offset+22],_buffer[debug_offset+23]);
					pointer_to_raw_data = Endiness.IntLittleToBigEndian(_buffer[debug_offset+24],_buffer[debug_offset+25],_buffer[debug_offset+26],_buffer[debug_offset+27]);
				}
				else
				{
					characteristics = Endiness.IntBigToLittleEndian(_buffer[debug_offset],_buffer[debug_offset+1],_buffer[debug_offset+2],_buffer[debug_offset+3]);
					time_date_stamp = Endiness.IntBigToLittleEndian(_buffer[debug_offset+4],_buffer[debug_offset+5],_buffer[debug_offset+6],_buffer[debug_offset+7]);
					major_version = Endiness.ShortBigToLittleEndian(_buffer[debug_offset+8],_buffer[debug_offset+9]);
					minor_version = Endiness.ShortBigToLittleEndian(_buffer[debug_offset+10],_buffer[debug_offset+11]);
					type = Endiness.IntBigToLittleEndian(_buffer[debug_offset+12],_buffer[debug_offset+13],_buffer[debug_offset+14],_buffer[debug_offset+15]);
					size_of_data = Endiness.IntBigToLittleEndian(_buffer[debug_offset+16],_buffer[debug_offset+17],_buffer[debug_offset+18],_buffer[debug_offset+19]);
					address_of_raw_data = Endiness.IntBigToLittleEndian(_buffer[debug_offset+20],_buffer[debug_offset+21],_buffer[debug_offset+22],_buffer[debug_offset+23]);
					pointer_to_raw_data = Endiness.IntBigToLittleEndian(_buffer[debug_offset+24],_buffer[debug_offset+25],_buffer[debug_offset+26],_buffer[debug_offset+27]);
				}

				debug_image.Characteristics = characteristics;
				debug_image.TimeDateStamp = time_date_stamp;
				debug_image.MajorVersion = major_version;
				debug_image.MinorVersion = minor_version;
				debug_image.Type = type;
				debug_image.SizeOfData = size_of_data;
				debug_image.AddressOfRawData = address_of_raw_data;
				debug_image.PointerToRawData = pointer_to_raw_data;
		
				if(type == DebugDirectory.IMAGE_DEBUG_TYPE_CODEVIEW)
				{
					debug_offset = address_of_raw_data-_rva;
					//RSDS http://www.godevtool.com/Other/pdb.htm
					DebugCodeViewInfo cv = new DebugCodeViewInfo();
		
					int guid_size = GUID.GUID_SIZE;
					int signature;
					byte [] guid = new byte[guid_size];
					int age;
					int file_name_size = size_of_data-8-guid_size-1;
					byte [] file_name = new byte[file_name_size];

					if(_little_endian)
					{
						signature = Endiness.IntLittleToBigEndian(_buffer[debug_offset],_buffer[debug_offset+1],_buffer[debug_offset+2],_buffer[debug_offset+3]);
						age = Endiness.IntLittleToBigEndian(_buffer[debug_offset+4+guid_size],_buffer[debug_offset+5+guid_size],_buffer[debug_offset+6+guid_size],_buffer[debug_offset+7+guid_size]);
					}
					else
					{
						signature = Endiness.IntBigToLittleEndian(_buffer[debug_offset],_buffer[debug_offset+1],_buffer[debug_offset+2],_buffer[debug_offset+3]);
						age = Endiness.IntBigToLittleEndian(_buffer[debug_offset+4+guid_size],_buffer[debug_offset+5+guid_size],_buffer[debug_offset+6+guid_size],_buffer[debug_offset+7+guid_size]);
					}
					int i;
					for(i = 0;i < guid_size;i++)
						guid[i] = _buffer[debug_offset+4+i];
					for(i = 0;i < file_name_size;i++)
						file_name[i] = _buffer[debug_offset+8+guid_size+i];

					cv.Signature = signature;
					cv.GUID = new GUID(guid);
					cv.Age = age;
					cv.Filename = file_name;

					debug_image.DebugInformation = cv; 
				}
	
				_text.DebugDirectory = debug_image;
			}
		}
	}
}
